(function(jwplayer) {


    /** Displays closed captions or subtitles on top of the video. **/
    var template = function(_player, options, _div) {


        /** Dimensions of the display. **/
        var _dimensions;
        /** Dock icons. **/
        var _icons = [
            '../assets/is_off.png',
            '../assets/is_on.png'
        ];
        /** Default configuration options. **/
        var _options = {
            back: false,
            color: '#FFFFFF',
            fontFamily: 'Arial,sans-serif',
            fontSize: 15,
            fontStyle: 'normal',
            fontWeight: 'normal',
            state: true,
            textDecoration: 'none'
        };
        /** Reference to the text renderer. **/
        var _renderer;
        /** Reference to the language selector. **/
        var _selector;
        /** Current player state. **/
        var _state;
        /** Currently active captions track. **/
        var _track;
        /** List with all tracks. **/
        var _tracks = [];


        /** Read or write a cookie. **/
        function _cookie(name,value) {
            name = 'jwplayercaptions' + name;
            if(value !== undefined) {
                var c = name+'='+value+'; expires=Wed, 1 Jan 2020 00:00:00 UTC; path=/';
                document.cookie = c;
            } else {
                // http://www.quirksmode.org/js/cookies.html
                var list = document.cookie.split(';');
                for(var i=0; i< list.length; i++) {
                    var c = list[i];
                    while (c.charAt(0) == ' ') {
                        c = c.substring(1,c.length);
                    }
                    if (c.indexOf(name) == 0) {
                        return c.substring(name.length+1, c.length);
                    }
                }
            }
            return null;
        };


        /** Dock button was clicked. **/
        var dockHandler = function() {
            if(_tracks.length > 1) {
                _selector.show();
                _renderer.hide();
                try {
                    _player.getPlugin('display').hide();
                    _player.getPlugin('dock').hide();
                } catch (error) {}
            } else if(_tracks.length == 1) {
                _options.state = !_options.state;
                _cookie('state',_options.state);
                _redraw();
            }
        };


        /** Error loading/parsing the captions. **/
        function _errorHandler(error) {
            console.log("CAPTIONS(" + error + ")");
        };


        /** Controlbar is hiding. **/
        function _hideHandler(event) {
            _renderer.resize(_dimensions[0],Math.round(_dimensions[1]*.94));
        };


        /** Player jumped to idle state. **/
        function _idleHandler(event) {
            _state = 'idle';
            _redraw();
        };


        /** Check if the device is touch, in which case captions are not rendered. **/
        function _isTouch() {
            var agent = navigator.userAgent.toLowerCase();
            if (agent.match(/ip(hone|ad|od)/i) !== null || 
                agent.match(/android/i) !== null) {
                return true;
            } else {
                return false;
            }
        };


        /** Listen to playlist item updates. **/
        function _itemHandler(event) {
            _track = 0;
            _tracks = [];
            _renderer.update(0);
            _selector.hide();
            try {
                _player.getPlugin('display').show();
                _player.getPlugin('dock').show();
            } catch (error) {}
            try {
                _player.getPlugin('display').show();
                _player.getPlugin('dock').show();
            } catch (error) {}
            var item = _player.getPlaylist()[event.index];
            // Load multiple captions
            if(item['captions.files']) {
                var found = false;
                var files = item['captions.files'].split(',');
                if(item['captions.labels']) {
                    var labels = item['captions.labels'].split(',');
                }
                for(var i=0; i<files.length; i++) {
                    var entry = { file: files[i] };
                    // Set label
                    if(labels && labels[i]) {
                        entry.label = labels[i];
                    } else {
                        entry.label = files[i].substring(files[i].lastIndexOf('/')+1,files[i].indexOf('.')-1);
                    }
                    // Matched label from cookie.
                    if(_options.label == entry.label) {
                        found = true;
                        _track = _tracks.length;
                        _load(entry.file);
                    }
                    _tracks.push(entry);
                }
                if(_tracks.length > 1) {
                    if(found == false) {
                        _options.state = false;
                    }
                    // populate selector
                    var options = [{label:'(Off)'}];
                    for(var j=0; j<_tracks.length; j++) {
                        options.push({label:_tracks[j].label});
                    }
                    if(_options.state) {
                        _selector.populate(options, _track+1);
                    } else {
                        _selector.populate(options, 0);
                    }
                } else {
                    // Single entry after all.
                    _load(_tracks[0].file);
                }
            // Load single caption
            } else if(item['captions.file']) {
                _tracks.push({file:item['captions.file']});
                _load(_tracks[0].file);
            }
            _redraw();
        };


        /** Load captions. **/
        function _load(file) {
            var loader = new jwplayer.captions.srt(_loadHandler,_errorHandler);
            loader.load(file);
        };


        /** Captions were loaded. **/
        function _loadHandler(data) {
            _renderer.populate(data);
            _tracks[_track].data = data;
            _redraw();
        };


        /** Player started playing. **/
        function _playHandler(event) {
            _state = 'playing';
            _redraw();
        };


        /** Insert global file/files on playlist update. **/
        function _playlistHandler(event) {
            if(_options.file) {
                _player.getPlaylist()[0]['captions.file'] = _options.file;
            }
            if(_options.files) {
                _player.getPlaylist()[0]['captions.files'] = _options.files;
            } 
            if(_options.labels) {
                _player.getPlaylist()[0]['captions.labels'] = _options.labels;
            }
        };


        /** Update the interface. **/
        function _redraw() {
            if(!_tracks.length) {
                _player.getPlugin("dock").setButton('captions');
                _renderer.hide();
            } else if (_options.state) {
                _player.getPlugin("dock").setButton('captions',dockHandler,_icons[1]);
                if(_state == 'playing') {
                    _renderer.show();
                } else {
                    _renderer.hide();
                }
            } else {
                _player.getPlugin("dock").setButton('captions',dockHandler,_icons[0]);
                _renderer.hide();
            }
        };


        /** Reposition elements upon a resize. **/
        this.resize = function(width,height) {
            if(_player.getRenderingMode() == 'flash' || _isTouch()) { return; }
            _selector.resize(width,height);
            _renderer.resize(width,Math.round(height*0.94));
            _dimensions = [width,height];
        };


        /** Set dock buttons when player is ready. **/
        function _setup() {
            if(_player.getRenderingMode() == 'flash' || _isTouch()) { return; }
            // Listen to player events
            _player.onPlaylist(_playlistHandler);
            _player.onPlaylistItem(_itemHandler);
            _player.onIdle(_idleHandler);
            _player.onPlay(_playHandler);
            _player.onTime(_timeHandler);
            try { 
                _player.getPlugin('controlbar').onHide(_hideHandler);
                _player.getPlugin('controlbar').onShow(_showHandler);
            } catch (error) {}
            // Grab cookies and config options
            if(_cookie('state') !== null) {
                if(_cookie('state') == 'true') { 
                    _options.state = true;
                } else {
                    _options.state = false;
                }
            }
            if(_cookie('label') !== null) {
                _options.label = _cookie('label');
            }
            for (var option in options) {
                _options[option] = options[option];
            }
            // Place renderer and selector.
            _renderer = new jwplayer.captions.renderer(_options,_div);
            _selector = new jwplayer.captions.selector(_selectorHandler,_div);
            _redraw();
        };
        _player.onReady(_setup);


        /** Selection menu was closed. **/
        function _selectorHandler(index) {
            // Show dock/display for 5.7+
            _selector.hide();
            try {
                _player.getPlugin('display').show();
                _player.getPlugin('dock').show();
            } catch (error) {}
            // Store new state and track
            if(index > 0) {
                _options.state = true;
                _track = index - 1;
                _options.label = _tracks[_track].label;
            } else {
                _options.state = false;
            }
            _cookie('label',_options.label);
            _cookie('state',_options.state);
            // Load new captions
            if(_tracks[_track].data) {
                _renderer.populate(_tracks[_track].data);
            } else {
                _load(_tracks[_track].file);
            }
            _redraw();
        };


        /** Controlbar is showing. **/
        function _showHandler(event) {
            var yps = event.boundingRect.y;
            if(yps > 0) { 
                _renderer.resize(_dimensions[0],Math.round(yps*.94));
            }
        };


        /** Listen to player time updates. **/
        function _timeHandler(event) {
            _renderer.update(event.position);
        };


    };


    /** Claim the namespace and register the plugin. **/
    jwplayer.captions = {};
    jwplayer().registerPlugin('captions', template,'./captions.swf');


})(jwplayer);